//package com.fy.fyspace.common.limiter;
//
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.core.script.DefaultRedisScript;
//import org.springframework.stereotype.Component;
//
//import java.util.Collections;
//import java.util.concurrent.TimeUnit;
//
///**
// * 基于Redis+Lua的令牌桶限流器
// */
//@Slf4j
//@Component
//public class RedisTokenBucketRateLimiter implements RateLimiter {
//    private static final int CHUNK_SIZE = 4 * 1024; // 4KB
//    private final RedisTemplate<String, Object> redisTemplate;
//    private final String bucketKey;
//    private final int tokensPerSecond;
//    private final DefaultRedisScript<Long> rateLimiterScript;
//
//    // Lua脚本实现令牌桶算法
//    private static final String RATE_LIMITER_SCRIPT =
//            "local key = KEYS[1]\n" +
//                    "local rate = tonumber(ARGV[1])\n" +
//                    "local capacity = tonumber(ARGV[2])\n" +
//                    "local now = tonumber(ARGV[3])\n" +
//                    "local permits = tonumber(ARGV[4])\n" +
//                    "\n" +
//                    "local bucket = redis.call('hmget', key, 'lastRefillTime', 'tokens')\n" +
//                    "local lastRefillTime = tonumber(bucket[1])\n" +
//                    "local tokens = tonumber(bucket[2])\n" +
//                    "\n" +
//                    "if lastRefillTime == nil then\n" +
//                    "    lastRefillTime = now\n" +
//                    "    tokens = capacity\n" +
//                    "end\n" +
//                    "\n" +
//                    "local delta = math.max(0, now - lastRefillTime)\n" +
//                    "local refillTokens = math.floor((delta * rate) / 1000000)\n" +
//                    "tokens = math.min(capacity, tokens + refillTokens)\n" +
//                    "lastRefillTime = now\n" +
//                    "\n" +
//                    "local enoughTokens = false\n" +
//                    "if tokens >= permits then\n" +
//                    "    enoughTokens = true\n" +
//                    "    tokens = tokens - permits\n" +
//                    "end\n" +
//                    "\n" +
//                    "redis.call('hmset', key, 'lastRefillTime', lastRefillTime, 'tokens', tokens)\n" +
//                    "redis.call('expire', key, math.ceil(capacity/rate)*2)\n" +
//                    "\n" +
//                    "return enoughTokens and 1 or 0";
//
//    public RedisTokenBucketRateLimiter(RedisTemplate<String, Object> redisTemplate,
//                                       Long ratePerSecond,
//                                       String userId) {
//        this.redisTemplate = redisTemplate;
//        this.tokensPerSecond = (int) (ratePerSecond / CHUNK_SIZE);
//        this.bucketKey = "rate_limiter:" + userId;
//
//        this.rateLimiterScript = new DefaultRedisScript<>(RATE_LIMITER_SCRIPT, Long.class);
//
//        log.info("Created rate limiter for user: {}, rate: {} bytes/s, tokens/s: {}",
//                userId, ratePerSecond, tokensPerSecond);
//    }
//
//    @Override
//    public boolean tryAcquire(int bytes) {
//        int tokensNeeded = (bytes + CHUNK_SIZE - 1) / CHUNK_SIZE; // 向上取整
//
//        try {
//            // 获取当前微秒时间戳
//            long now = System.nanoTime() / 1000;
//
//            // 执行Lua脚本
//            Long result = redisTemplate.execute(
//                    rateLimiterScript,
//                    Collections.singletonList(bucketKey),
//                    tokensPerSecond,           // rate: 每秒补充的令牌数
//                    tokensPerSecond,           // capacity: 桶容量
//                    now,                       // now: 当前微秒时间戳
//                    tokensNeeded               // permits: 需要的令牌数
//            );
//
//            boolean acquired = result != null && result == 1;
//            if (acquired) {
//                log.debug("Acquired {} tokens for {} bytes", tokensNeeded, bytes);
//            } else {
//                log.debug("Failed to acquire {} tokens for {} bytes", tokensNeeded, bytes);
//            }
//            return acquired;
//
//        } catch (Exception e) {
//            log.error("Redis rate limiter error", e);
//            return false;
//        }
//    }
//
//    @Override
//    public boolean tryAcquire(int bytes, long timeout, TimeUnit unit) {
//        long timeoutMicros = TimeUnit.MICROSECONDS.convert(timeout, unit);
//        long startTime = System.nanoTime() / 1000;
//
//        do {
//            if (tryAcquire(bytes)) {
//                return true;
//            }
//            try {
//                TimeUnit.MILLISECONDS.sleep(1);
//            } catch (InterruptedException e) {
//                Thread.currentThread().interrupt();
//                return false;
//            }
//        } while ((System.nanoTime() / 1000) - startTime < timeoutMicros);
//
//        return false;
//    }
//}